home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / interp / perl-5.003.tar.gz / perl-5.003.tar / perl-5.003 / lib / Cwd.pm < prev    next >
Text File  |  1996-03-25  |  6KB  |  272 lines

  1. package Cwd;
  2. require 5.000;
  3. require Exporter;
  4.  
  5. =head1 NAME
  6.  
  7. getcwd - get pathname of current working directory
  8.  
  9. =head1 SYNOPSIS
  10.  
  11.     use Cwd;
  12.     $dir = cwd;
  13.  
  14.     use Cwd;
  15.     $dir = getcwd;
  16.  
  17.     use Cwd;
  18.     $dir = fastgetcwd;
  19.  
  20.     use Cwd 'chdir';
  21.     chdir "/tmp";
  22.     print $ENV{'PWD'};
  23.  
  24. =head1 DESCRIPTION
  25.  
  26. The getcwd() function re-implements the getcwd(3) (or getwd(3)) functions
  27. in Perl.
  28.  
  29. The fastcwd() function looks the same as getcwd(), but runs faster.
  30. It's also more dangerous because you might conceivably chdir() out of a
  31. directory that you can't chdir() back into.
  32.  
  33. The cwd() function looks the same as getcwd and fastgetcwd but is
  34. implemented using the most natural and safe form for the current
  35. architecture. For most systems it is identical to `pwd` (but without
  36. the trailing line terminator). It is recommended that cwd (or another
  37. *cwd() function) is used in I<all> code to ensure portability.
  38.  
  39. If you ask to override your chdir() built-in function, then your PWD
  40. environment variable will be kept up to date.  (See
  41. L<perlsub/Overriding builtin functions>.) Note that it will only be
  42. kept up to date it all packages which use chdir import it from Cwd.
  43.  
  44. =cut
  45.  
  46. @ISA = qw(Exporter);
  47. @EXPORT = qw(cwd getcwd fastcwd fastgetcwd);
  48. @EXPORT_OK = qw(chdir);
  49.  
  50. # use strict;
  51.  
  52. sub _backtick_pwd {  # The 'natural and safe form' for UNIX (pwd may be setuid root)
  53.     my $cwd;
  54.     chop($cwd = `pwd`);
  55.     $cwd;
  56.  
  57. # Since some ports may predefine cwd internally (e.g., NT)
  58. # we take care not to override an existing definition for cwd().
  59.  
  60. *cwd = \&_backtick_pwd unless defined &cwd;
  61.  
  62.  
  63. # By Brandon S. Allbery
  64. #
  65. # Usage: $cwd = getcwd();
  66.  
  67. sub getcwd
  68. {
  69.     my($dotdots, $cwd, @pst, @cst, $dir, @tst);
  70.  
  71.     unless (@cst = stat('.'))
  72.     {
  73.     warn "stat(.): $!";
  74.     return '';
  75.     }
  76.     $cwd = '';
  77.     $dotdots = '';
  78.     do
  79.     {
  80.     $dotdots .= '/' if $dotdots;
  81.     $dotdots .= '..';
  82.     @pst = @cst;
  83.     unless (opendir(PARENT, $dotdots))
  84.     {
  85.         warn "opendir($dotdots): $!";
  86.         return '';
  87.     }
  88.     unless (@cst = stat($dotdots))
  89.     {
  90.         warn "stat($dotdots): $!";
  91.         closedir(PARENT);
  92.         return '';
  93.     }
  94.     if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
  95.     {
  96.         $dir = '';
  97.     }
  98.     else
  99.     {
  100.         do
  101.         {
  102.         unless (defined ($dir = readdir(PARENT)))
  103.             {
  104.             warn "readdir($dotdots): $!";
  105.             closedir(PARENT);
  106.             return '';
  107.         }
  108.         unless (@tst = lstat("$dotdots/$dir"))
  109.         {
  110.             warn "lstat($dotdots/$dir): $!";
  111.             # Just because you can't lstat this directory
  112.             # doesn't mean you'll never find the right one.
  113.             # closedir(PARENT);
  114.             # return '';
  115.         }
  116.         }
  117.         while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
  118.            $tst[1] != $pst[1]);
  119.     }
  120.     $cwd = "$dir/$cwd";
  121.     closedir(PARENT);
  122.     } while ($dir);
  123.     chop($cwd); # drop the trailing /
  124.     $cwd;
  125. }
  126.  
  127.  
  128.  
  129. # By John Bazik
  130. #
  131. # Usage: $cwd = &fastcwd;
  132. #
  133. # This is a faster version of getcwd.  It's also more dangerous because
  134. # you might chdir out of a directory that you can't chdir back into.
  135.  
  136. sub fastcwd {
  137.     my($odev, $oino, $cdev, $cino, $tdev, $tino);
  138.     my(@path, $path);
  139.     local(*DIR);
  140.  
  141.     ($cdev, $cino) = stat('.');
  142.     for (;;) {
  143.     my $direntry;
  144.     ($odev, $oino) = ($cdev, $cino);
  145.     chdir('..');
  146.     ($cdev, $cino) = stat('.');
  147.     last if $odev == $cdev && $oino == $cino;
  148.     opendir(DIR, '.');
  149.     for (;;) {
  150.         $direntry = readdir(DIR);
  151.         next if $direntry eq '.';
  152.         next if $direntry eq '..';
  153.  
  154.         last unless defined $direntry;
  155.         ($tdev, $tino) = lstat($direntry);
  156.         last unless $tdev != $odev || $tino != $oino;
  157.     }
  158.     closedir(DIR);
  159.     unshift(@path, $direntry);
  160.     }
  161.     chdir($path = '/' . join('/', @path));
  162.     $path;
  163. }
  164.  
  165.  
  166. # Keeps track of current working directory in PWD environment var
  167. # Usage:
  168. #    use Cwd 'chdir';
  169. #    chdir $newdir;
  170.  
  171. my $chdir_init = 0;
  172.  
  173. sub chdir_init {
  174.     if ($ENV{'PWD'} and $^O ne 'os2') {
  175.     my($dd,$di) = stat('.');
  176.     my($pd,$pi) = stat($ENV{'PWD'});
  177.     if (!defined $dd or !defined $pd or $di != $pi or $dd != $pd) {
  178.         $ENV{'PWD'} = cwd();
  179.     }
  180.     }
  181.     else {
  182.     $ENV{'PWD'} = cwd();
  183.     }
  184.     # Strip an automounter prefix (where /tmp_mnt/foo/bar == /foo/bar)
  185.     if ($ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|) {
  186.     my($pd,$pi) = stat($2);
  187.     my($dd,$di) = stat($1);
  188.     if (defined $pd and defined $dd and $di == $pi and $dd == $pd) {
  189.         $ENV{'PWD'}="$2$3";
  190.     }
  191.     }
  192.     $chdir_init = 1;
  193. }
  194.  
  195. sub chdir {
  196.     my $newdir = shift || '';    # allow for no arg (chdir to HOME dir)
  197.     $newdir =~ s|///*|/|g;
  198.     chdir_init() unless $chdir_init;
  199.     return 0 unless CORE::chdir $newdir;
  200.     if ($^O eq 'VMS') { return $ENV{'PWD'} = $ENV{'DEFAULT'} }
  201.  
  202.     if ($newdir =~ m#^/#) {
  203.     $ENV{'PWD'} = $newdir;
  204.     } else {
  205.     my @curdir = split(m#/#,$ENV{'PWD'});
  206.     @curdir = ('') unless @curdir;
  207.     my $component;
  208.     foreach $component (split(m#/#, $newdir)) {
  209.         next if $component eq '.';
  210.         pop(@curdir),next if $component eq '..';
  211.         push(@curdir,$component);
  212.     }
  213.     $ENV{'PWD'} = join('/',@curdir) || '/';
  214.     }
  215.     1;
  216. }
  217.  
  218.  
  219. # --- PORTING SECTION ---
  220.  
  221. # VMS: $ENV{'DEFAULT'} points to default directory at all times
  222. # 06-Mar-1996  Charles Bailey  bailey@genetics.upenn.edu
  223. # Note: Use of Cwd::chdir() causes the logical name PWD to be defined
  224. #   in the process logical name table as the default device and directory 
  225. #   seen by Perl. This may not be the same as the default device 
  226. #   and directory seen by DCL after Perl exits, since the effects
  227. #   the CRTL chdir() function persist only until Perl exits.
  228.  
  229. sub _vms_cwd {
  230.     return $ENV{'DEFAULT'}
  231. }
  232. sub _os2_cwd {
  233.     $ENV{'PWD'} = `cmd /c cd`;
  234.     chop $ENV{'PWD'};
  235.     $ENV{'PWD'} =~ s:\\:/:g ;
  236.     return $ENV{'PWD'};
  237. }
  238.  
  239. my($oldw) = $^W;
  240. $^W = 0;  # assignments trigger 'subroutine redefined' warning
  241. if ($^O eq 'VMS') {
  242.  
  243.     *cwd        = \&_vms_cwd;
  244.     *getcwd     = \&_vms_cwd;
  245.     *fastcwd    = \&_vms_cwd;
  246.     *fastgetcwd = \&_vms_cwd;
  247. }
  248. elsif ($^O eq 'NT') {
  249.  
  250.     *getcwd     = \&cwd;
  251.     *fastgetcwd = \&cwd;
  252. }
  253. elsif ($^O eq 'os2') {
  254.     *cwd     = \&_os2_cwd;
  255.     *getcwd     = \&_os2_cwd;
  256.     *fastgetcwd = \&_os2_cwd;
  257.     *fastcwd = \&_os2_cwd;
  258. }
  259. $^W = $oldw;
  260.  
  261. # package main; eval join('',<DATA>) || die $@;    # quick test
  262.  
  263. 1;
  264.  
  265. __END__
  266. BEGIN { import Cwd qw(:DEFAULT chdir); }
  267. print join("\n", cwd, getcwd, fastcwd, "");
  268. chdir('..');
  269. print join("\n", cwd, getcwd, fastcwd, "");
  270. print "$ENV{PWD}\n";
  271.